var WORKER_INVOKE_CALLBACK_ID = 1;
const Queue = require('bull');

class Agent {
    constructor(app) {
        this.app = app;
    }

    async serverDidReady() {
        debugger;
        const testQueue = new Queue("testQueue", {
            redis: { port: 6379, host: '127.0.0.1', password: null }
        });

        testQueue.process(async (job, done) => {
            this.app.logger.info(`worker:${process.pid}, job:${job.data.index}`);
            try {
                const res = await this.invokeWorkerAsync({
                    method: 'service.testService.doTest',
                    data: {
                        id: 100
                    }
                });
            } catch (err) { } finally {
                done();
            }

        });
        this.app.testQueue = testQueue;
    }

    /**
     * 异步通知随机Worker并等待Worker返回消息
     * @param {*} param0 
     * @returns 
     */
    invokeWorkerAsync({ method, data, needCallback = true }) {
        const app = this.app;
        function doInvoke(callbackId) {
            app.messenger.sendRandom('worker_invoke', { method, data, callbackId });
        };
        if (needCallback) {
            let callbackResolve, callbackReject;
            const eventId = `worker_invoke_callback:${WORKER_INVOKE_CALLBACK_ID++}`;
            const callback = (res) => {
                if (timeoutId !== 0) {
                    clearTimeout(timeoutId);
                    timeoutId = 0;
                }
                if (res.error) {
                    callbackReject(new Error(res.error));
                } else {
                    callbackResolve(res.data);
                }
            };
            app.messenger.once(eventId, callback);
            let timeoutId = setTimeout(() => {
                if (timeoutId === 0) {
                    return;
                }
                timeoutId = 0;
                app.messenger.off(eventId, callback);
                callbackReject(new Error('Worker invoke timeout!'));
            }, 30 * 1000);// 30秒超时，移除该事件侦听
            doInvoke(eventId);
            return new Promise((resolve, reject) => {
                callbackResolve = resolve;
                callbackReject = reject;
            });

        } else {
            doInvoke();
        }

    }
}

module.exports = Agent;